//author : shike@outlook.com
//  date : 2013/07/10
// brief : 定义VOIP使用的TCP连接类

#ifndef BASE_VOIP_TCP_TASK_H_
#define BASE_VOIP_TCP_TASK_H_

#include "Zebra.h"
#include "ct_noncopyable.h"
#include "ctSocket.h"
#include "ctLog.h"
#include "AudioCommand.h"
#include <queue>
#include <list>

class ctVOIPThreadPool;
class ctVOIPTCPOkayThread;
class ctVOIPTCPTask
{
        public:
                enum TerminateMethod
                {
                        terminate_no,		//not terminate
                        terminate_active,	//client close
                        terminate_passive,	//server close
                };
                ctVOIPTCPTask(ctVOIPThreadPool *pool, 
                                const int sock, 
                                const struct sockaddr_in *addr = NULL)
                        : mSocket(sock, addr, false), pool(pool)
                {
                        terminate = terminate_no;
                        terminate_wait = false;
                        fdsradd = false;
                        okay_thread_ = NULL;
                        user_id_ = 0;
                        channel_id_ = 0;
                        data_flags_ = 0;
                }
                virtual ~ctVOIPTCPTask()
                {
                }
                inline void addEpollFD(int kdpfd,__uint32_t events, void* ptr)
                {
                        mSocket.addEpoll(kdpfd,events, ptr);
                }
                inline void delEpollFD(int kdpfd,__uint32_t events)
                {
                        mSocket.delEpoll(kdpfd, events);
                }
                inline bool isFdsrAdd()
                {
                        return fdsradd;
                }
                inline bool fdsrAdd()
                {
                        fdsradd=true;
                        return fdsradd;
                }
                virtual int verifyConn()
                {
                        return 1;
                }
                inline const char *getIP() const
                {
                        return mSocket.getIP();
                }
                inline const DWORD getAddr() const
                {
                        return mSocket.getAddr();
                }
                inline const WORD getPort() const
                {
                        return mSocket.getPort();
                }
                inline ctVOIPThreadPool *getPool()
                {
                        return pool;
                }
                inline int sock() const
                {
                        return mSocket.Sock();
                }
                bool sendCmd(const void *,int len, bool buffer=true);
                bool sendCmdNoPack(const void *,int);
                bool ListeningRecv(bool);
                bool ListeningSend();
                bool msgParse(const AudioCmd::stUDPPkgHead *cmd, const DWORD &cmdlen);
                void disableMediaData(uint8_t type, bool enable);
                bool isTerminateWait()
                {
                        return terminate_wait;
                }

                void TerminateWait()
                {
                        Zebra::logger->trace("%s:socket(%u)", __PRETTY_FUNCTION__, mSocket.Sock());
                        terminate_wait=true;
                }
                bool isTerminate() const
                {
                        return terminate_no != terminate;
                }
                virtual void Terminate(const TerminateMethod method = terminate_passive)
                {
                        terminate = method;
                }
                inline void setOkayThread(ctVOIPTCPOkayThread *thread)
                {
                        okay_thread_ = thread;
                }
                inline const DWORD getUserID() const 
                {
                        return user_id_;
                }
                inline void setUserID(const DWORD &userid) 
                {
                        user_id_ = userid;
                }
                inline void setChannelID(const DWORD &channelid)
                {
                        channel_id_ = channelid;
                }
                inline const DWORD getChannelID() const 
                {
                        return channel_id_;
                }


        protected:
                ctSocket mSocket;
                uint8_t data_flags_;  // flags for disable media data.
        private:
                ctVOIPThreadPool *pool;         //task in which pool
                ctVOIPTCPOkayThread *okay_thread_;
                bool fdsradd;                   //read event add flag
                TerminateMethod terminate;
                bool terminate_wait;

                DWORD user_id_;
                DWORD channel_id_;

                t_BufferCmdQueue rcv_queue_rtp_;
                t_BufferCmdQueue rcv_queue_rtcp_;
};

class ctVOIPTCPTaskQueue
{
        public:
                ctVOIPTCPTaskQueue() 
                        :_size(0) 
                {
                }
                virtual ~ctVOIPTCPTaskQueue() 
                {
                }
                inline void add(ctVOIPTCPTask *task)
                {
                        mlock.lock();
                        _queue.push(task);
                        _size++;
                        mlock.unlock();
                }

        protected:
                inline void check_queue()
                {
                        mlock.lock();
                        while(!_queue.empty()) {
                                _temp_queue.push(_queue.front());
                                _queue.pop();
                        }
                        _size = 0;
                        mlock.unlock();
                        while(!_temp_queue.empty()) {
                                ctVOIPTCPTask *task =_temp_queue.front();
                                _temp_queue.pop();
                                Zebra::logger->debug("tasks push taskid:%u", task->sock());
                                _add(task);
                        }
                }

        protected:
                virtual void _add(ctVOIPTCPTask *task) = 0;
                DWORD _size;

        private:
                ctMutex mlock;
                std::queue<ctVOIPTCPTask *, std::deque<ctVOIPTCPTask *> >  _queue;
                std::queue<ctVOIPTCPTask *, std::deque<ctVOIPTCPTask *> >  _temp_queue;
};

/**
 * \brief 连接任务链表
 */
typedef std::list<ctVOIPTCPTask *> ctTCPTaskContainer;
typedef ctTCPTaskContainer::iterator ctTCPTask_IT;

typedef std::vector<struct epoll_event> epollfdContainer;

#endif //BASE_VOIP_TCP_TASK_H_
